# encoding: UTF-8
'''
Created: 2014-05-06 15:26

@author: VAN
'''
import select
import socket
import thread


class SimpleSockServer:
    def __init__(self, port, max_conn_count=5):
        self.srvsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.srvsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.srvsock.bind(('', port))
        self.srvsock.listen(max_conn_count)
        self.clients = {}
        
        print "SockServer startup on port %s and max connect count %s" % (port, max_conn_count)
    
    def run(self):
        while 1:
            rsock, address = self.srvsock.accept()
            self.clients[address] = rsock
            print 'new client : ' + repr(address)
            thread.start_new_thread(self.msg_handler, (rsock, address))
        
    def msg_handler(self, rsock, address):
        while 1:
            try:
                # recv
                buf = rsock.recv(1024)
                print "recv: " + repr(address) + " & " + buf
                print "clients count: %d " % self.clients.__len__();
                if len(self.clients) == 1: 
                    rsock.send("default : " + repr(address))
                    continue;
                 
                # transf   
                for key in self.clients.keys():
                    if key == address:
                        continue
                    else:
                        s = self.clients[key];
                        s.sendall("transf : " + repr(key) + "&" + buf)
            except Exception, e:
                print "error : ", e
                self.clients.pop(address)
                rsock.close()
                thread.exit_thread()
        
    
    def close(self, csock):
        if csock:
            self.clients.remove(csock)
            csock.close()
            
        
class SelectSockServer:
    sever_transf_label = 's#$&'
    def __init__(self, port):
        self.port = port
        self.srvsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.srvsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.srvsock.setblocking(False)
        self.srvsock.bind(('', port))
        self.srvsock.listen(5)
        
        self.ins = [self.srvsock]
        self.clients = {}
        
        print 'SelectServer started on port %s' % port
    
    def run(self):
        while 1:
            readable, writeable, exps = select.select(self.ins, [], [], 5)
            if not readable or writeable or exps:
                continue
            for rsock in readable:
                if rsock is self.srvsock:
                    self.accept_new_connection()
                else:
                    try:
                        buf = rsock.recv(1024)
                        print "server recv : ", buf
                        if buf.startswith(SelectSockServer.sever_transf_label):
                            continue
                        if buf :
                            host, port = rsock.getpeername()
                            rsp = SelectSockServer.sever_transf_label + 'transf [%s:%s] %s' % (host, port, buf)
                            self.transf(rsp, rsock)
                        else:
                            host, port = rsock.getpeername()
                            buf = 'Client left %s:%s\r\n' % (host, port)
                            self.ins.remove(rsock)
                            self.clients.pop(rsock)
                            
                            rsock.close()
                    except Exception, e:
                        print "error : ", e
                        self.ins.remove(rsock)
                        self.clients.pop(rsock)
                            
                        rsock.close()
                        
                
            
            for rsock in exps:
                print " exception condition on ", rsock.getpeername()
                self.ins.remove(rsock)
                rsock.close()
    
    
    def accept_new_connection(self):
        rsock, address = self.srvsock.accept()
        rsock.setblocking(0)
        self.ins.append(rsock)
        self.clients[rsock] = address
        print "new client : " , address
        rsock.send('hello,welcome !')
        
    def transf(self, msg, omit_sock):
        print "rsp : ", msg + " clients :" + repr(len(self.clients))
        if len(self.clients) == 1:
            omit_sock.send("just only you")
            return
        for rsock in self.clients.keys():
            if rsock is omit_sock:
                continue
            rsock.send(msg)
            
                


# SimpleSockServer(8002).run()

SelectSockServer(8002).run()
